﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RbmlVisualizer.Data;
using RbmlVisualizer.Data.Blocks;

namespace RbmlVisualizer.Scoring
{
    public class ScoringEngine
    {
        private readonly List<ClassifierBlock> _initalUmlBlocks = new List<ClassifierBlock>();
        private readonly List<ClassifierBlock> _initialRbmlBlocks = new List<ClassifierBlock>();
        public double Score { get { return (_localScore * .75 + .25 * _globalScore) * 100; } }

        private double _localScore;
        private double _globalScore;

        public void RegisterUmlBlocks(IEnumerable<ClassifierBlock> classifierBlocks)
        {
            _initalUmlBlocks.AddRange(classifierBlocks);
        }

        public void RegisterRbmlBlocks(IEnumerable<ClassifierBlock> classifierBlocks)
        {
            _initialRbmlBlocks.AddRange(classifierBlocks);
        }

        public void ScoreLocalyConformingBlocks(Dictionary<ClassifierBlock, List<ClassifierBlock>> classifierBlocks)
        {
            var rbmlBlocks = GetUniqueRbmlBlocks(classifierBlocks);
            var umlBlocks = GetUniqueUmlBlocks(classifierBlocks);
            var rbmlBlocksCount = (float)rbmlBlocks.Count;
            var umlBlocksCount = (float)umlBlocks.Count;
            _localScore = (2.0 / 3.0) * (rbmlBlocksCount / (_initialRbmlBlocks.Count)) + (1.0 / 3.0) * (umlBlocksCount / (_initalUmlBlocks.Count));
        }

        public void ScoreGloballyConformingBlocks(Dictionary<ClassifierBlock, List<ClassifierBlock>> classifierBlocks)
        {
            var rbmlBlocks = GetUniqueRbmlBlocks(classifierBlocks);
            var umlBlocks = GetUniqueUmlBlocks(classifierBlocks);
            var rbmlBlocksCount = (float)rbmlBlocks.Count;
            var umlBlocksCount = (float)umlBlocks.Count;
            _globalScore = (2.0 / 3.0) * (rbmlBlocksCount / (_initialRbmlBlocks.Count)) + (1.0 / 3.0) * (umlBlocksCount / (_initalUmlBlocks.Count));
        }

        private static List<ClassifierBlock> GetUniqueUmlBlocks(Dictionary<ClassifierBlock, List<ClassifierBlock>> classifierBlocks)
        {
            var conformingUmlBlocks = new List<ClassifierBlock>();
            foreach (var classifierBlock in classifierBlocks.Values)
            {
                conformingUmlBlocks.AddRange(classifierBlock.Where(b => !conformingUmlBlocks.Contains(b)));
            }

            return conformingUmlBlocks;
        }

        private static List<ClassifierBlock> GetUniqueRbmlBlocks(Dictionary<ClassifierBlock, List<ClassifierBlock>> classifierBlocks)
        {
            return classifierBlocks.Keys.Where(k => classifierBlocks[k].Count > 0).ToList();
        }


    }
}
